package com.guyaogg.gulimall.auth.controller;

import com.alibaba.fastjson.TypeReference;
import com.guyaogg.common.constant.AuthServerConstant;
import com.guyaogg.common.exception.BizCodeEnum;
import com.guyaogg.common.utils.R;
import com.guyaogg.gulimall.auth.feign.MemberFeignService;
import com.guyaogg.gulimall.auth.feign.ThirdPartFeignService;
import com.guyaogg.gulimall.auth.vo.UserRegisterVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author 顾遥
 */
@Controller
@Slf4j
public class RegController {
    private final StringRedisTemplate redisTemplate;
    private final MemberFeignService memberFeignService;
    private final ThirdPartFeignService thirdPartFeignService;

    public RegController(StringRedisTemplate redisTemplate, MemberFeignService memberFeignService, ThirdPartFeignService thirdPartFeignService) {
        this.redisTemplate = redisTemplate;
        this.memberFeignService = memberFeignService;
        this.thirdPartFeignService = thirdPartFeignService;
    }

    @ResponseBody
    @GetMapping("/sms/sendCode")
    public R sendCode(@RequestParam("phone") String phone) {

        // TODO 1.接口防刷


        // 60s 频率
        String val = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
        if (!StringUtils.isEmpty(val)) {
            long preTime = Long.parseLong(val.split("_")[1]);
            long reSendTimeout = 60 * 1000;
            if (System.currentTimeMillis() - preTime < reSendTimeout) {
                return R.error(BizCodeEnum.SMS_CODE_EXCEPTION);
            }
        }
        String code = UUID.randomUUID().toString().substring(0, 5);
        String redisCode = code + "_" + System.currentTimeMillis();
        // 2.验证码再次校验。redis 存 key - value -> sms:code:18168071756  -> code
        redisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone, redisCode, 10, TimeUnit.MINUTES);

        return thirdPartFeignService.sendCode(phone, code);
    }
    /**
     * 注册成功回到首页或登录页
     *  // TODO 重定向携带数据，利用 session 原理，将数据放入 session 中
     *
     *  // TODO 分布式下的 session 问题
     * @param redirectAttributes // 模拟重定向携带数据
     * @return
     */
    @PostMapping("/register")
    public String register(@Validated UserRegisterVO vo, BindingResult result,
                           RedirectAttributes redirectAttributes) {
        log.debug("注册数据：{}", vo);
        if (result.hasErrors()) {
            Map<String, String> errors = new HashMap<>(result.getErrorCount());
            result.getFieldErrors().forEach(fieldError -> {
                String field = fieldError.getField();
                String message = fieldError.getDefaultMessage();
                errors.put(field, message);
            });
            log.info("注册数据错误：{}", errors);

            redirectAttributes.addFlashAttribute("errors", errors);
            // Request method 'POST' not supported
            // 校验出错，转发到注册页
            return "redirect:http://auth.gulimall.com/reg.html";
        }
        // 真正注册

        // 1.校验验证码
        String redisCode = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
        if(!StringUtils.isEmpty(redisCode)){
            String code = redisCode.split("_")[0];
            if(Objects.equals(vo.getCode(), code)){
                // 删除验证码,令牌机制
                redisTemplate.delete(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
                // 验证通过.真正注册，调用远程服务注册
                R r = memberFeignService.register(vo);
                if(r.getCode() == 0){
                    // 成功
                    return "redirect:http://auth.gulimall.com/login.html";
                }else {
                    // 失败
                    Map<String, String> errors = new HashMap<>(1);
                    errors.put("msg", r.getData("msg", new TypeReference<String>(){}));
                    redirectAttributes.addFlashAttribute("errors",errors);
                    return "redirect:http://auth.gulimall.com/reg.html";
                }

            }else {
                HashMap<String, String> errors = new HashMap<>(1);
                errors.put("code", "验证码错误");
                redirectAttributes.addFlashAttribute("errors", errors);
                return "redirect:http://auth.gulimall.com/reg.html";
            }

        }else {
            HashMap<String, String> errors = new HashMap<>(1);
            errors.put("code", "验证码过期");
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/reg.html";
        }


    }


}
